package com.sojson.util.lock;

import java.util.concurrent.TimeUnit;

import com.sojson.config.exception.TransErrorCode;
import com.sojson.constant.Constant;
import com.sojson.util.ExpUtil;
import com.sojson.util.StringUtil;
import com.sojson.util.lock.impl.DistributedLockRedissonUtilImpl;
import com.sojson.util.properties.PropertiesUtil;
import com.sojson.util.text.Convert;

/**
 * 分布式锁工具类
 *
 * @author liu
 * @date 2020-11-15
 */
public class LockUtil {

    /** 锁缓存持久化的时候为了和其他属性区分加的前缀,不设置为lock */
    public static final String CACHE_NAME_PREFIX_LOCK =
        StringUtil.getKeyBase(Convert.toStr(Constant.PROPERTIES.getProperty("so.cache.name.prefix.lock"), "lock"))
            + StringUtil.J;
    /** 获取锁的超时时间(单位: 秒,不设置为10秒) */
    public static final Integer TIMEOUT_GET =
        Convert.toInt(PropertiesUtil.getNumberFormat(Constant.PROPERTIES.getProperty("so.lock.timeout.get")), 10);
    /** 使用锁的超时时间(单位: 秒,不设置为30秒) */
    public static final Integer TIMEOUT_USE =
        Convert.toInt(PropertiesUtil.getNumberFormat(Constant.PROPERTIES.getProperty("so.lock.timeout.use")), 30);
    /** 使用锁的超时时间(单位: 毫秒,不设置为30秒) */
    public static final Integer TIMEOUT_USE_MILLIS = TIMEOUT_USE * 1000;
    /** 锁的超时时间单位 */
    public static final TimeUnit TIME_UNIT = TimeUnit.SECONDS;
    /** 超时时间(永久) */
    public static final int TIMEOUT_LONG = -1;
    private static final DistributedLockUtilInterface DISTRIBUTED_LOCK_UTIL_INTERFACE =
        DistributedLockRedissonUtilImpl.getInstances();

    /**
     * 获取锁
     *
     * @param lockName 锁名称
     * @return
     */
    public static CustomLock getLock(String lockName) {
        return DISTRIBUTED_LOCK_UTIL_INTERFACE.getLock(lockName);
    }

    /**
     * 上锁
     *
     * @param lockName 锁名称
     * @return
     * @throws Exception
     */
    public static CustomLock lock(String lockName) throws Exception {
        return lock(lockName, TIMEOUT_GET);
    }

    /**
     * 在给定的时间内上锁
     *
     * @param lockName      锁名称
     * @param timeOutGet    获取锁的超时时间(单位: 秒,不设置为10秒)
     * @return
     * @throws Exception
     */
    public static CustomLock lock(String lockName, long timeOutGet) throws Exception {
        return lock(lockName, timeOutGet, TIME_UNIT);
    }

    /**
     * 在给定的时间内上锁
     *
     * @param lockName      锁名称
     * @param timeOutGet    获取锁的超时时间(不设置为10秒)
     * @param unit          获取锁的超时时间单位
     * @return
     * @throws Exception
     */
    public static CustomLock lock(String lockName, long timeOutGet, TimeUnit unit) throws Exception {
        return lock(lockName, timeOutGet, TIMEOUT_USE, unit);
    }

    /**
     * 在给定的时间内获取锁
     *
     * @param lockName      锁名称
     * @param timeOutGet    获取锁的超时时间(单位: 秒,不设置为10秒)
     * @param timeOutUse    使用锁的超时时间(单位: 秒,不设置为30秒)
     * @return
     * @throws Exception
     */
    public static CustomLock lock(String lockName, long timeOutGet, long timeOutUse) throws Exception {
        return lock(lockName, timeOutGet, timeOutUse, TIME_UNIT);
    }

    /**
     * 在给定的时间内获取锁
     *
     * @param lockName      锁名称
     * @param timeOutGet    获取锁的超时时间(单位: 秒,不设置为10秒)
     * @param timeOutUse    使用锁的超时时间(单位: 秒,不设置为30秒)
     * @param unit          锁的超时时间单位
     * @return
     * @throws Exception
     */
    public static CustomLock lock(String lockName, long timeOutGet, long timeOutUse, TimeUnit unit) throws Exception {
        CustomLock lock = getLock(lockName);
        boolean status = lock.lock(timeOutGet, timeOutUse, unit);
        if (!status) {
            ExpUtil.throwEx(TransErrorCode.THREAD_BUSY);
        }
        return lock;
    }

}